package com.service.token.rest;


import com.service.core.rest.response.BaseResponse;
import com.service.core.rest.response.OneResponse;
import com.service.core.rest.response.TokenResponse;
import com.service.token.enums.TokenEnum;
import com.service.token.request.TokenGenerationRequest;
import com.service.utility.common.ExceptionUtil;
import com.service.utility.common.UUIDUtil;
import com.service.utility.datetime.DateTimeUtil;
import com.service.utility.jwt.JWTHeader;
import com.service.utility.jwt.JWTPayload;
import com.service.utility.jwt.JWTUtil;
import com.service.utility.jwt.UserDefinedPayload;
import com.service.utility.modelmapper.ModelMapperUtil;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import static com.service.core.constant.BusinessStatus.TOKEN_ERROR;

@Api(tags = "Token管理")
@Controller
@RequestMapping(value = "/token", headers = {"api-version=1.0", "Authorization"})
public class TokenController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private Environment env;

    @ApiOperation("生成Token")
    @RequestMapping(value = "/generate", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 400, message = "参数异常(400)"),
            @ApiResponse(code = 200, message = "生成TOKEN成功(200)"),
            @ApiResponse(code = 500, message = "服务器异常(500)")})
    public @ResponseBody
    OneResponse<TokenResponse> generate(@ApiParam @RequestBody TokenGenerationRequest request, @RequestHeader("Authorization") String authorization, HttpServletResponse response) {
        String uuid = UUIDUtil.randomUUID();
        logger.info("生成Token request:{}, uuid:{}", request, uuid);

        OneResponse<TokenResponse> oneResponse = new OneResponse<>();
        TokenResponse tokenResponse = new TokenResponse();
        if (request.getSource() == null || !StringUtils.equals(env.getProperty("project.authorization"), authorization)) {
            oneResponse.setStatus(HttpStatus.BAD_REQUEST.value());
            oneResponse.setDesc("参数异常");
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            logger.info("参数异常 uuid:{}", uuid);
            return oneResponse;
        }

        UserDefinedPayload userDefinedPayload = ModelMapperUtil.map(request, UserDefinedPayload.class);
        JWTPayload payload = generateJwtPayload(userDefinedPayload, request.getSource());

        try {
            String token = JWTUtil.generateJWT(new JWTHeader(), payload, env.getProperty("jwt.secret"));
            tokenResponse.setToken(token);
            oneResponse.setStatus(HttpStatus.OK.value());
            oneResponse.setDesc("请求成功");
            oneResponse.setData(tokenResponse);
            logger.info("生成Token成功 uuid:{}", uuid);
            return oneResponse;
        } catch (UnsupportedEncodingException e) {
            oneResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            oneResponse.setDesc("服务器异常");
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            logger.warn(ExceptionUtil.getStackTraceAsString(e));
            logger.info("服务器异常 uuid:{}", uuid);
            return oneResponse;
        }
    }

    @ApiOperation("校验Token接口")
    @RequestMapping(value = "/verifyToken", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "Token正确(200), Token错误(100004)")})
    public @ResponseBody
    BaseResponse verifyToken(@ApiParam @RequestBody String token) {
        String uuid = UUIDUtil.randomUUID();
        logger.info("校验 token:{}, uuid:{}", token, uuid);

        try {
            JWTUtil.verifyToken(token, env.getProperty("jwt.secret"));
        } catch (Exception e) {
            logger.info("Token校验失败 uuid:{}", uuid);
            return new BaseResponse(TOKEN_ERROR.value(), TOKEN_ERROR.getReasonPhrase());
        }
        logger.info("Token校验成功 uuid:{}", uuid);
        return new BaseResponse(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase());
    }

    private JWTPayload generateJwtPayload(UserDefinedPayload userDefinedPayload, TokenEnum.TokenSource source) {
        JWTPayload payload = new JWTPayload();
        payload.setIss(env.getProperty("jwt.payload.iss"));
        payload.setIat(new Date());

        if (source == TokenEnum.TokenSource.ADMIN) {
            payload.setExp(DateTimeUtil.getThreeOclockAMOfTheNextDay());  //过期时间为第二天的凌晨三点钟
        } else if (source == TokenEnum.TokenSource.END_USER) {
            payload.setExp(DateTimeUtil.getThreeOclockAMOfSeventhDay());  //过期时间为第七天的凌晨三点钟
        }

        payload.setJti(UUIDUtil.randomUUID());
        payload.setUserId(userDefinedPayload.getUserId());
        payload.setPid(userDefinedPayload.getPid());
        payload.setAccount(userDefinedPayload.getAccount());
        payload.setMobile(userDefinedPayload.getMobile());
        payload.setSessionId(userDefinedPayload.getSessionId());
        return payload;
    }

}
